package com.p2p.base.exception;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

public class ExceptionResolver extends SimpleMappingExceptionResolver{

	private static final Logger	log							= LoggerFactory.getLogger(ExceptionResolver.class);

	/**
	 * business_exception_
	 */
	public static final String	BUSINESS_EXCEPTION_PREFIX	= "business_exception_";

	@Resource
	private ApplicationContext	context;

	@Override
	protected ModelAndView getModelAndView(String viewName,Exception exception,HttpServletRequest request){
		if (exception instanceof BusinessException){
			BusinessException businessException = (BusinessException) exception;
			exception = encode(businessException);			
			
		}else {
			log.warn("", exception);
		}
		if (request.getHeader("X-Requested-With") != null){
			Map<String,Object> exceptionMap = new HashMap<String,Object>();
			if(exception instanceof BusinessException){
				exceptionMap.put("statusCode", ((BusinessException)exception).getErrorCode());
				List<String> messages = new ArrayList<String>();
				messages.add(exception.getMessage());
				while(((BusinessException) exception).getLinkedException()!= null){
					exception = ((BusinessException) exception).getLinkedException();
					messages.add(exception.getMessage());
				}
				exceptionMap.put("message", messages);
				
			}else{
				exceptionMap.put("statusCode", 600);
				exceptionMap.put("message", exception.getMessage());
			}
			
			exceptionMap.put("cause", exception.getCause());			
			ModelAndView mv = new ModelAndView("json");
			mv.getModel().put("exception", exceptionMap);
			return mv;
		}
		return super.getModelAndView(viewName, exception, request);
	}

	private BusinessException encode(BusinessException businessException){
		String key = BUSINESS_EXCEPTION_PREFIX + businessException.getErrorCode();
		String errorCode = businessException.getErrorCode();
		Object[] args = businessException.getArgs();
		String message = context.getMessage(key, args, key, LocaleContextHolder.getLocale());
		Object[] objects = { errorCode, key, args, message };
		log.error("errorCode:{},key:{},args:{},message:{}", objects);
		BusinessException result = new BusinessException(errorCode, message);
		result.setArgs(args);
		if (businessException.getLinkedException() != null){
			result.setLinkedException(encode(businessException.getLinkedException()));
		}
		return result;
	}
}
